<!--
 * @Author: zengwj
 * @Date: 2022-06-21 13:52:25
 * @LastEditors: zengwj
 * @LastEditTime: 2022-06-22 14:14:15
 * @Description: 
-->
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    function sayName(other, age) {
      console.log(`${other}say name is ${this.name} and age is ${age}`)
    }
    const person = {
      name: 'zwj'
    }
    Function.prototype.myCall = function (content, ...args) {
      if (typeof this !== "function") {
        throw new Error("Type error");
      }
      // 保证不会重写content 目标对象的值
      const fnSymbol = Symbol()
      content[fnSymbol] = this
      const result = content[fnSymbol](...args)
      delete content[fnSymbol]
      return result
    }
    Function.prototype.myApply = function (content, args) {
      if (typeof this !== "function") {
        throw new Error("Type error");
      }
      const fnSymbol = Symbol()
      content[fnSymbol] = this
      const result = content[fnSymbol](...args)
      delete content[fnSymbol]
      return result
    }
    // sayName.myApply(person, ['张三', 18])
    // sayName.myCall(person, '张三', 18)
    // sayName.call(person, '张三')
    // Function.prototype.mybind = function (content) {
    //   if (typeof this !== "function") {
    //     throw new Error("Type error");
    //   }
    //   const arges = [...arguments].slice(1)
    //   const fn = this
    //   return function Fn() {
    //     return fn.apply(
    //       this instanceof Fn ? this : content,
    //       // 当前的这个 arguments 是指 Fn 的参数
    //       arges.concat(...arguments)
    //     )
    //   }
    // }
    Function.prototype.mybind = function (content) {
      if (typeof this !== 'function') {
        return new TypeError('fuck you')
      }
      const fn = this
      const arges = [...arguments].slice(1)
      return function Fn() {
        return fn.apply(
          // 如果是构造函数 指向的是构造函数本身，一般函数指向目标对象
          this instanceof Fn ? this : content,
          [...arges, ...arguments]
        )
      }
    }

    const nn = sayName.mybind(person, '张三')
    let obj = new nn(18)
  </script>

</body>

</html>